package com.mapbased.cc;

import java.io.IOException;
import java.util.Map;

import com.mapbased.wfw.*;
import org.dom4j.Element;
import com.mapbased.cc.form.FormElement;
import java.util.List;
import com.mapbased.cc.form.CustomFormElement;
import com.mapbased.cc.form.PasswordFormElement;
import com.mapbased.cc.form.TextAreaFormElement;
import org.dom4j.Attribute;
import com.mapbased.cc.form.TitleFormElement;
import com.mapbased.cc.form.EditAreaFormElement;
import com.mapbased.cc.form.HtmlEditAreaFormElement;
import com.mapbased.wfw.PageLoader.LoadContext;

/**
 * <p>Title: </p>
 *
 * <p>Description: </p>
 *
 * <p>Copyright: Copyright (c) 2005</p>
 *
 * <p>Company: mapbased.com</p>
 *
 * @author Chang Huanyou (Baily)
 * @version 1.0
 */
public class Form
    extends Component implements Validating
{
    FormElement[] _elements;
    Object[] attributes;
    String td1;
    String td2;
    String td3;
    String table;

    Binding elementsBinding;

    /**
     * a component can choose to parse an element or not.
     *
     * @param ele Element
     * @param loader PageLoader
     * @return Element or null:if wanna page loader parse the
     *   component,return the ele, else return null
     * @todo Implement this com.mapbased.wfw.Component method
     */
    public Element parseXml(Element ele,
                            com.mapbased.wfw.PageLoader.LoadContext lc)
    {

        List l=ele.elements("formelement");

        String mapbinding=ele.attributeValue("formelements","");
        if(mapbinding.length() > 0)
        {
            LoadContext nlc=new LoadContext(lc);
            List ll=nlc.segments;
            lc.loader.parseBinding(mapbinding,nlc);
            try
            {
                this.elementsBinding=(Binding)ll.get(0);
            }
            catch(Exception ex1)
            {
                throw new java.lang.RuntimeException(
                    "Error getting Form elements binding:"
                    + mapbinding);
            }

        }
        else
        {

            this.parseFormElements(lc,l);
        }
        Attribute a=ele.attribute("jwcid");
        if(a != null)
        {
            ele.remove(a);
        }
        //////////////////////////////////////////////////

        a=ele.attribute("td1");
        if(a != null)
        {
            ele.remove(a);
            this.td1=a.getValue();
        }
        a=ele.attribute("td2");
        if(a != null)
        {
            ele.remove(a);
            this.td2=a.getValue();
        }
        a=ele.attribute("td3");
        if(a != null)
        {
            ele.remove(a);
            this.td3=a.getValue();
        }
        a=ele.attribute("table");
        if(a != null)
        {
            ele.remove(a);
            this.table=a.getValue();
        }

        PageLoader.LoadContext nlc=new PageLoader.LoadContext(lc);

        PageLoader.StringBufferBag bag=nlc.last;
        List segs=nlc.segments;

        bag.buffer.append("<form ");
        lc.loader.parseAttributes(ele.attributes(),nlc);
        bag.buffer.append(" >");
        segs.add(bag.getString());
        this.attributes=segs.toArray();

        segs.clear();
        l=ele.elements();
        for(int i=0;i < l.size();i++)
        {
            Element e=(Element)l.get(i);
            if(e.getName().equals("formelement"))
            {
            }
            else
            {
                lc.loader.parseElement(e,nlc);
            }

        }
        bag.buffer.append("</form>");

        segs.add(bag.getString());

        this.segments=segs.toArray();

        return null;
    }

    private void parseFormElements(PageLoader.LoadContext pl,List l)
    {
        this._elements=new FormElement[l.size()];
        for(int i=0;i < l.size();i++)
        {
            Element e=(Element)l.get(i);
            String s=e.attributeValue("type");
            FormElement fe=null;
            if(s == null || s.equals(""))
            {
                fe=new FormElement();
            }
            else if(s.equalsIgnoreCase("custom"))
            {
                fe=new CustomFormElement();

            }
            else if(s.equalsIgnoreCase("password"))
            {
                fe=new PasswordFormElement();

            }
            else if(s.equalsIgnoreCase("textarea"))
            {
                fe=new TextAreaFormElement();

            }
            else if(s.equalsIgnoreCase("editor") ||
                    s.equalsIgnoreCase("editarea"))
            {
                fe=new EditAreaFormElement();

            }
            else if(s.startsWith("html"))
            {
                fe=new HtmlEditAreaFormElement();
            }

            else if(s.equalsIgnoreCase("title"))
            {
                fe=new TitleFormElement();
            }
            else if(s.equalsIgnoreCase("group"))
            {
                fe=new com.mapbased.cc.form.GroupFormElement();
            }
            else
            {
                throw new java.lang.RuntimeException(
                    "unknow type for FormElement:" + s);
            }

            this._elements[i]=fe;
            fe.init(e,pl);

        }

    }

    private static final FormElement[] EMPTY_ELEMENTS=new FormElement[0];
    protected FormElement[] getFormElements(RenderContext r)
    {
        if(this.elementsBinding == null)
        {
            return this._elements;
        }
        else
        {
            FormElement[] fe=(FormElement[])this.elementsBinding.getValue(r);
            if(fe == null)
            {
                return EMPTY_ELEMENTS;
            }
            return fe;
        }

    }

    /**
     * render
     *
     * @param context RenderContext
     * @throws IOException
     * @todo Implement this com.mapbased.wfw.Component method
     */
    public void render(RenderContext r)
        throws IOException
    {
        defalutRenderBehavior(r,this.attributes);

        //.......................
        java.io.Writer w=r.getOutputWriter();
        w.write("<table ");
        if(this.table != null)
        {
            w.write(this.table);
        }
        w.write(" >");
        Map m=(Map)r.getRequestMap().get(Constants.Valid_Errors);
        FormElement[] elements=this.getFormElements(r);

        for(int i=0;i < elements.length;i++)
        {
            FormElement fe=elements[i];

            w.write("<tr ");
            if(m != null && m.containsKey(fe.getName()))
            {
                w.write("class=\"highlight_true\" ");
            }
            w.write(">");
            if(fe instanceof TitleFormElement)
            {
                w.write("<td colspan=\"3\" class=\"title\">");
                w.write(fe.getCaption());
                w.write("</td>");
            }
            else if(fe.getDescribe() == fe.NO_DESC)
            {
                w.write("<td  class=\"label\" ");

                if(this.td1 != null)
                {
                    w.write(td1);
                }
                w.write(" >");
                w.write(fe.getCaption());
                w.write(":</td>");
//------------------------------------------------------------------
                w.write("<td  colspan=\"2\" ");
                if(this.td2 != null)
                {
                    w.write(td2);
                }
                w.write(" >");

                fe.renderInputPart(r);

                w.write("</td>");

            }
            else
            {
                w.write("<td class=\"label\" ");
                if(this.td1 != null)
                {
                    w.write(td1);
                }
                w.write(" >");
                w.write(fe.getCaption());
                w.write(":</td>");
//------------------------------------------------------------------
                w.write("<td ");
                if(this.td2 != null)
                {
                    w.write(td2);
                }
                w.write(" >");

                fe.renderInputPart(r);

                w.write("</td>");

                //-------------------------------------
                w.write("<td class=\"desc\" ");
                if(this.td3 != null)
                {
                    w.write(td3);
                }
                w.write(" >");

                defalutRenderBehavior(r,fe.getDescribe());
                w.write("</td>");

            }

            w.write("</tr>");

        }
        w.write("</table>");

        defalutRenderBehavior(r,this.segments);
    }

    /**
     * renderHeader
     *
     * @param context RenderContext
     * @param sb StringBuffer
     * @param m Map
     * @todo Implement this com.mapbased.wfw.Component method
     */
    public void renderHeader(RenderContext r,StringBuffer sb,Map m)
    {

        if(!m.containsKey(this.getClass()))
        {
            m.put(this.getClass(),this);
            //   sb.append(this.headString);
            renderBinding(r,this.headSegments,sb);

        }

    }

    public void validate(RenderContext rc)
    {
        FormElement[] elements=this.getFormElements(rc);

        for(int i=0;i < elements.length;i++)
        {
            elements[i].validate(rc);
        }
    }
}
